#!/usr/bin/env node
console.log('img5%4.js loaded');
// 图片转为 5:4 比例，保证图片完全显示，空白部分填充为白色
import fs from 'fs';
import path from 'path';
import sharp from 'sharp';
import pLimit from 'p-limit';

const limit = pLimit(5);

const TARGET_RATIO = 5 / 4; // 5:4

function findImages(dir) {
	let results = [];
	const list = fs.readdirSync(dir);

	list.forEach(file => {
		const filePath = path.join(dir, file);
		const stat = fs.statSync(filePath);

		if (stat && stat.isDirectory()) {
			results = results.concat(findImages(filePath));
		} else if (/\.(png|jpe?g)$/i.test(file)) {
			results.push(filePath);
		}
	});

	return results;
}

async function padTo5by4(filePath) {
	const tmpPath = `${filePath}.tmp`;
	try {
		const img = sharp(filePath);
		const meta = await img.metadata();

		const w = meta.width || 0;
		const h = meta.height || 0;

		if (!w || !h) {
			console.warn(`无法读取图片尺寸：${filePath}`);
			return;
		}

		const curRatio = w / h;

		// 如果已经是 5:4（允许非常小的浮点误差），跳过
		if (Math.abs(curRatio - TARGET_RATIO) < 1e-6) {
			console.log(`已为 5:4，跳过：${filePath}`);
			return;
		}

		// 目标尺寸：在保持原始图片不裁剪、不放大/缩小的前提下
		// 选择以原图的短边不变，并在较短的那一边上扩展以满足 5:4 比例
		let targetW, targetH;

		if (curRatio < TARGET_RATIO) {
			// 图片比 5:4 更窄 → 需要扩宽画布
			targetH = h;
			targetW = Math.round(h * TARGET_RATIO);
		} else {
			// 图片比 5:4 更宽 → 需要扩高画布
			targetW = w;
			targetH = Math.round(w / TARGET_RATIO);
		}

		// 计算居中放置的偏移
		const left = Math.floor((targetW - w) / 2);
		const top = Math.floor((targetH - h) / 2);

		// 创建白色背景画布，然后将原图居中合成
		const canvas = sharp({
			create: {
				width: targetW,
				height: targetH,
				channels: 3,
				background: { r: 255, g: 255, b: 255 },
			},
		});

		// 将原图放到白色背景的画布上并直接写到临时文件
		const ext = path.extname(filePath).toLowerCase();
		if (ext === '.jpg' || ext === '.jpeg') {
			await canvas
				.composite([{ input: await img.toBuffer(), left, top }])
				.jpeg({ quality: 90 })
				.toFile(tmpPath);
		} else {
			// 输出为 png（保持有无透明通道都变成不透明白底）
			await canvas
				.composite([{ input: await img.toBuffer(), left, top }])
				.png({ compressionLevel: 9 })
				.toFile(tmpPath);
		}

		// 覆盖原图
		fs.renameSync(tmpPath, filePath);
		console.log(`已转换为 5:4 并填充白色：${filePath} → ${targetW}x${targetH}`);
	} catch (err) {
		console.error(`处理失败：${filePath}`, err);
		if (fs.existsSync(tmpPath)) fs.unlinkSync(tmpPath);
	}
}

async function processDir(root) {
	if (!fs.existsSync(root)) {
		console.error('找不到路径：', root);
		return;
	}

	const images = fs.statSync(root).isDirectory() ? findImages(root) : [root];
	console.log(`找到 ${images.length} 张图片，开始处理（将居中填充白色至 5:4）...`);

	const tasks = images.map(p => limit(() => padTo5by4(p)));
	await Promise.all(tasks);
	console.log('全部处理完成。');
}

const args = process.argv.slice(2);
if (!args[0]) {
	console.error('用法：node img5%4.js <图片文件或目录>');
	process.exit(1);
}

processDir(args[0]);